﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using KylinORM.CQRS.Publisher;

namespace KylinORM.CQRS.Subscriber
{
    /// <summary>
    /// 消息响应
    /// </summary>
    public class MessageHandler
    {
        public MessageHandler()
        {
        }
        public MessageHandler(params Delegate[] callbackFunc)
        {
            foreach (Delegate d in callbackFunc)
                this.AddItem(new MessageHandlerItem(d));
        }
        public MessageHandler(params MessageHandlerItem[] handlerItem)
        {
            this.AddItem(handlerItem);
        }

        private List<MessageHandlerItem> handlerItems = new List<MessageHandlerItem>();

        /// <summary>
        /// 添加一个消息响应明细及其依赖项
        /// </summary>
        /// <param name="handlerItem"></param>
        /// <returns></returns>
        public MessageHandler AddItem(params MessageHandlerItem[] handlerItem)
        {
            handlerItems.AddRange(handlerItem);
            return this;
        }

        /// <summary>
        /// 接收一条消息，并执行响应
        /// </summary>
        /// <param name="message"></param>
        public void Apply(IMessage message)
        {
            foreach (MessageHandlerItem handlerItem in this.handlerItems.OrderBy(d => (int)d.MessageLevel))
            {
                this.ApplyMessage(message, handlerItem);
            }
        }
        protected virtual void ApplyMessage(IMessage message, MessageHandlerItem handlerItem)
        {
            //执行依赖条件
            foreach (MessageHandlerItem item in handlerItem.dependsOn.OrderBy(d => (int)d.MessageLevel))
            {
                this.ApplyMessage(message, item);
            }
            //执行响应的回调方法
            EMessageType messageType = handlerItem.MessageType ?? message.MessageType;
            if (message.MessageType == messageType)
            {
                handlerItem.CallbackFunc.DynamicInvoke(message);
            }
            else
            {
                Action<IMessage> action = (cmd) => handlerItem.CallbackFunc.DynamicInvoke(message);
                action.BeginInvoke(message, null, null);
            }
        }

    }
}
